package asteroids.entity.weapon;

import java.awt.Color;

import org.apache.log4j.Logger;

import asteroids.engine.Utils;
import asteroids.entity.GameObject;
import asteroids.entity.Icing;
import asteroids.entity.Ship;
import asteroids.factory.ShapeLib;

public class Explosion extends Bullet
{
    Logger logger = Logger.getLogger(Explosion.class);

    private double explosion_radius;
    private double max_explosion_radius;
    private double shrapnel_size = ShapeLib.shipLength;
    /*
     * keeps track of the explosion progress: 1 - warming up 2 - BOOM 3 -
     * cleanup?
     */
    private int phase;
    private long phaseStartTime; // when the current phase began
    private long currentTime; // how long we've been in the current phase

    /**
     * 
     * @param explosionRadius
     *            - the size of the blast. Will determine the kill range.
     * @param size
     *            - the approximate size of the generated debris - Normally use
     *            the maximum radius of the exploding object.
     */
    public Explosion(double xpos, double ypos, double explosionRadius, boolean hurts, Ship ship)
    {
        super(xpos, ypos, 0, 0, (hurts) ? 1 : 0, Utils.createPolarCircle(1), ship);
        affiliation = GameObject.NONE;
        phaseStartTime = 0;
        currentTime = 0;
        phase = 1;
        max_explosion_radius = explosionRadius;
        color = Color.GRAY;
    }

    public Explosion(double xpos, double ypos, double explosionRadius, Ship ship)
    {
        this(xpos, ypos, explosionRadius, true, ship);
    }

    public Explosion(double xpos, double ypos, Ship ship)
    {
        this(xpos, ypos, ShapeLib.shipLength * 5, true, ship);
    }

    public void update()
    {
        logger.trace("Explosion.update()");
        if( phase == 1 && currentTime - phaseStartTime > 1 )
        {
            logger.trace("exploding!");

            // explode! - first create shrapnel
            double minShrapnels = (max_explosion_radius / ShapeLib.shipLength) * 35;
            for( int k = 0; k < (int) (Math.round(Math.random() * 50 + minShrapnels)); k++ )
            {
                // used to determine the size of the shrapnel bits.
                int s = (int) (Math.random() * (shrapnel_size - 4)) + 4;

                Utils.CartesianCoordinate coord = Utils.cartesianFromPolar(Utils
                        .createPolarCoordinate(Math.random() * 360 + 1, 0));

                Utils.PolarCoordinate[] icingShape = { Utils.createPolarCoordinate(0, s / 2),
                        Utils.createPolarCoordinate(180, s / 2) };

                Icing i = new Icing(x_position + coord.getXComponent(), y_position
                        + coord.getYComponent(), (int) (Math.random() * (Utils.FRAMES_PER_SECOND)),
                        icingShape, GameObject.ObjectType.ICING);

                i.setRotation(Math.random() * 360);
                i.setRotationSpeed(Math.random() * 360 / (1.5 * Utils.FRAMES_PER_SECOND) + 2.5);
                Utils.PolarCoordinate pVelocity = Utils.createPolarCoordinate(
                        Math.random() * 360 + 1, (max_explosion_radius * 5)
                                / Utils.FRAMES_PER_SECOND);
                i.setVelocity(Utils.cartesianFromPolar(pVelocity));
                icing.add(i);
            }

            phaseStartTime = currentTime;
            phase = 2;
        }
        else if( phase == 2 )
        {
            logger.trace("expanding explosion!");
            // expand explosion - looking for 1/10 of a second boom time
            double explosionTime = .1 * Utils.FRAMES_PER_SECOND;
            explosion_radius += max_explosion_radius / explosionTime;
            objectShape = Utils.createPolarCircle(explosion_radius);
            max_radius = explosion_radius;

            // if explosion is over, end
            if( currentTime - phaseStartTime > explosionTime )
            {
                logger.trace("ending explosion!");
                phase = 3; // prevent additional carnage
                drawMe = false;
            }
        }
        else if( phase == 3 && icing.size() == 0 )
        {
            logger.trace("explosion animation end");
            destroy();
        }
        currentTime++;
        super.update();
    }

    @Override
    public double getCollisionPower(GameObject other)
    {
        if( phase == 3 )
        {
            return 0;
        }
        else
        {
            return super.getCollisionPower(other);
        }
    }

    @Override
    public void collide(GameObject other, double power)
    {
        // do nothing. Explosions are impervious!
    }

    public String toString()
    {
        return "Explosion!";
    }
}
